package com.capgemini.daos;

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.NavigableMap;

import org.apache.hadoop.hbase.client.Delete;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.util.Bytes;

import com.capgemini.data.Discipline;
import com.capgemini.data.Performance;
import com.capgemini.data.Tournament;

public class TournamentDao extends Dao<Tournament> {

	private long tourcounter;
	private long perfcounter;

	public TournamentDao() {
		tourcounter = 0;
		perfcounter = 0;
	}

	public void addRow(Tournament type) {
		try {
			HTable table = new HTable(conf, "Tournament");
			long tourid;
			if (type.getId() == null || type.getId() == 0) {
				tourcounter++;
				tourid = tourcounter;
			} else {
				tourid = type.getId();
			}
			Put put = new Put(Bytes.toBytes(String.valueOf(tourid)));
			put.add(Bytes.toBytes("Info"), Bytes.toBytes("name"),
					Bytes.toBytes(type.getName()));
			put.add(Bytes.toBytes("Info"), Bytes.toBytes("edition"),
					Bytes.toBytes(Integer.toString(type.getEdition())));
			put.add(Bytes.toBytes("Info"), Bytes.toBytes("startDate"),
					Bytes.toBytes(type.getStartDate().toString()));
			put.add(Bytes.toBytes("Info"), Bytes.toBytes("endDate"),
					Bytes.toBytes(type.getEndDate().toString()));
			put.add(Bytes.toBytes("Info"), Bytes.toBytes("location"),
					Bytes.toBytes(type.getLocation()));
			put.add(Bytes.toBytes("Info"), Bytes.toBytes("sport"),
					Bytes.toBytes(type.getSport().toString()));
			Delete del = new Delete((String.valueOf(tourid)).getBytes());
			del.deleteFamily(Bytes.toBytes("Performance"));
			table.delete(del);
			for (Performance temp : type.getPerformances()) {
				long perfid;
				if (temp.getId() == null) {
					perfcounter++;
					perfid = perfcounter;
				} else {
					perfid = temp.getId();
				}
				temp.setId(perfid);
				put.add(Bytes.toBytes("Performance"),
						Bytes.toBytes(String.valueOf(tourid) + "/"
								+ String.valueOf(perfid)),
						Bytes.toBytes(temp.toPersistString()));
				if (temp.getAthlete() != 0) {
					Put p = new Put(("atl/" + temp.getAthlete()).getBytes());
					p.add(Bytes.toBytes("Performance"),
							Bytes.toBytes(String.valueOf(tourid) + "/"
									+ String.valueOf(perfid)),
							Bytes.toBytes(String.valueOf(tourid) + "/"
									+ String.valueOf(perfid)));
					HTable aTable = new HTable(conf, "Person");
					aTable.put(p);
				}
			}
			table.put(put);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public List<Tournament> getRecords() throws ParseException {
		List<Tournament> result = new ArrayList<Tournament>();
		try {
			HTable table = new HTable(conf, "Tournament");
			Scan s = new Scan();
			ResultScanner ss = table.getScanner(s);
			for (Result r : ss) {
				result.add(readTournament(r));
			}
		} catch (IOException e) {
			e.printStackTrace();
		}

		return result;
	}

	public static Tournament getRecord(String rowkey) throws IOException,
			ParseException {
		HTable table = new HTable(conf, "Tournament");
		Get get = new Get(rowkey.getBytes());
		Result rs = table.get(get);
		return readTournament(rs);
	}

	public static Tournament readTournament(Result r) throws ParseException {
		Tournament temp = new Tournament();
		temp.setId(Long.valueOf(new String(r.getRow())));
		temp.setName(new String(r.getValue(Bytes.toBytes("Info"),
				Bytes.toBytes("name"))));
		temp.setEdition(Integer.parseInt(new String(r.getValue(
				Bytes.toBytes("Info"), Bytes.toBytes("edition")))));
		temp.setLocation(new String(r.getValue(Bytes.toBytes("Info"),
				Bytes.toBytes("location"))));
		temp.setSport(Discipline.valueOf(new String(r.getValue(
				Bytes.toBytes("Info"), Bytes.toBytes("sport")))));
		String temps = new String(r.getValue(Bytes.toBytes("Info"),
				Bytes.toBytes("startDate")));

		DateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
		java.util.Date parsedUtilDate = formater.parse(temps);
		temp.setStartDate(new java.sql.Date(parsedUtilDate.getTime()));
		temps = new String(r.getValue(Bytes.toBytes("Info"),
				Bytes.toBytes("endDate")));
		parsedUtilDate = formater.parse(temps);
		temp.setEndDate(new java.sql.Date(parsedUtilDate.getTime()));
		NavigableMap<byte[], byte[]> resultmap = r.getFamilyMap(Bytes
				.toBytes("Performance"));
		for (byte[] perfbyte : resultmap.values()) {
			Performance newperf = new Performance();
			String str = new String(perfbyte);
			String tempstr = str.substring(16, str.indexOf(','));
			if (tempstr.equals("null")) {
				newperf.setId(0);
			} else {
				newperf.setId(Long.parseLong(tempstr));
			}
			str = str.substring(str.indexOf(',') + 9);
			tempstr = str.substring(0, str.indexOf(','));
			formater = new SimpleDateFormat("hh:mm:ss");
			parsedUtilDate = formater.parse(tempstr);
			newperf.setResult(new java.sql.Time(parsedUtilDate.getTime()));
			str = str.substring(str.indexOf(',') + 10);
			tempstr = str.substring(0, str.indexOf(','));
			newperf.setRanking(Integer.parseInt(tempstr));
			str = str.substring(str.indexOf(',') + 14);
			tempstr = str.substring(0, str.indexOf(']'));
			newperf.setWorldRecord(Boolean.getBoolean(tempstr));
			str = str.substring(str.indexOf(',') + 10);
			tempstr = str.substring(0, str.indexOf(']'));
			newperf.setAthlete(Long.valueOf(tempstr));
			newperf.setTournament(temp);
			temp.addPerformance(newperf);
		}
		return temp;
	}

	public static void delRecord(String tableName, String rowKey)
			throws Exception {
		HTable table = new HTable(conf, tableName);
		Tournament temp = getRecord(rowKey);
		HTable perstable = new HTable(conf, "Person");
		for (Performance perf : temp.getPerformances()) {
			if (perf.getAthlete() != 0) {
				Put put = new Put(Bytes.toBytes("atl/"
						+ String.valueOf((perf.getAthlete()))));
				put.add(Bytes.toBytes("Performance"),
						Bytes.toBytes(String.valueOf(temp.getId()) + "/"
								+ String.valueOf(perf.getId())), null);
				perstable.put(put);
			}
		}
		Delete del = new Delete(rowKey.getBytes());
		table.delete(del);
	}
}
